export const objectToString = (obj) => Object.prototype.toString.call(obj);

export const toStringType = (obj) => objectToString(obj).slice(8, -1);

export function isObject(obj) {
  return obj !== null && typeof obj === "object";
}

export const isArray = (obj) => Array.isArray(obj);

export const isNaN = (obj) => Number.isNaN(obj);

export const isInteger = (obj) => Number.isInteger(obj);

export const isType = (obj, type) => {
  return toStringType(obj) === type;
};

export const isFunction = (obj) => {
  return toStringType(obj) === "Function";
};

export function isBoolean(obj) {
  return toStringType(obj) === "Boolean";
}

export function isString(obj) {
  return typeof obj === "string";
}

export function isNumber(obj) {
  return toStringType(obj) === "Number";
}

export function isPlainObject(obj) {
  return toStringType(obj) === "Object";
}

export const isMap = (obj) => {
  return toStringType(obj) === "Map";
};

export const isSet = (obj) => {
  return toStringType(obj) === "Set";
};

export const isNull = (obj) => {
  return toStringType(obj) === "Null";
};

export const isUndefined = (obj) => {
  return toStringType(obj) === "Undefined";
};

export const isPromise = (obj) => {
  return toStringType(obj) === "Promise";
};

export const isSymbol = (obj) => {
  return toStringType(obj) === "Symbol";
};

export const isEmpty = (obj) => {
  if (isString(obj) || isArray(obj)) return obj.length === 0;
  if (isSet(obj) || isMap(obj)) return obj.size === 0;
  if (isPlainObject(obj)) return Reflect.ownKeys(obj).length === 0;
  throw new Error("Not one of [String, Array, Set, Map, PlainObject]");
};

export const isOdd = (n) => !!(n & 1);
export const isEven = (n) => !(n & 1);
